<template>
  <div class="treeTabel-wrap">
    <el-table
      ref="treeTabel"
      :header-cell-style="{
        background: 'rgba(233, 235, 239, 0.5000)',
        color: '#031129',
        borderBottom: '1px solid #E9EBEF',
      }"
      :cell-style="{
        borderBottom: '1px solid #E9EBEF',
      }"
      :data="tableData"
      border
      row-key="id"
      :row-class-name="rowClassNameFun"
      :header-row-class-name="headerRowClassName"
      size="mini"
      style="width: 100%"
      default-expand-all
      v-bind="$attrs"
      @select="setRowIsSelect"
      @select-all="selectAllFun"
      v-on="$listeners"
    >
      <template v-for="(cln, index) in tableColumn">
        <template v-if="cln.type == 'select'">
          <el-table-column
            :key="index"
            type="selection"
            :fixed="cln.fixed"
            :width="cln.width || 36"
            :selectable="cln.selectable"
          />
        </template>
        <template v-else-if="cln.type === 'radio'">
          <el-table-column
            :key="cln.id || cln.value || 'radio'"
            :width="cln.width || 36"
            :align="cln.align || 'center'"
            :disabled="cln.disabled || null"
            :enabled="cln.enabled || null"
          >
            <template slot-scope="scope">
              <el-radio
                v-if="
                  cln.disabled &&
                    scope.row[cln.enabled] == cln.disabled
                "
                v-model="radioSelect"
                class="table_radio"
                :label="scope.row"
                disabled
              >
                &nbsp;&nbsp;-
              </el-radio>
              <el-radio
                v-else
                v-model="radioSelect"
                class="table_radio"
                :label="scope.row"
              >
                &nbsp;&nbsp;-
              </el-radio>
            </template>
          </el-table-column>
        </template>
        <template v-else-if="cln.type == 'index'">
          <el-table-column
            :key="index"
            :label="'序号'"
            type="index"
            :prop="cln.value"
            width="50"
            :align="cln.align || 'center'"
          />
        </template>
        <template v-else-if="cln.type === 'render' && cln.render">
          <el-table-column
            :key="cln.id || cln.value || ''"
            :column-key="
              'treeTabel' + index + (cln.id || cln.value || '')
            "
            :label="cln.label"
            :prop="cln.value"
            :sortable="cln.sortable"
            :sort-method="cln.sortMethod"
            :fixed="cln.fixed"
            :width="cln.width"
            :class-name="cln.className"
            :align="cln.align || 'center'"
          >
            <template v-if="cln.headerRender" #header="scope">
              <com-functionRender
                :render="cln.headerRender"
                :data="{
                  row: scope.row,
                  column: cln,
                  index: scope.$index,
                }"
              />
            </template>
            <template v-else-if="cln.header" #header="scope">
              <slot v-bind="scope" :name="cln.header" />
            </template>
            <template slot-scope="scope">
              <com-functionRender
                :render="cln.render"
                :data="{
                  row: scope.row,
                  column: cln,
                  index: scope.$index,
                }"
              />
            </template>
          </el-table-column>
        </template>
        <template v-else>
          <el-table-column
            :key="'treeTabel' + index + (cln.id || cln.value || '')"
            :column-key="
              'treeTabel' + index + (cln.id || cln.value || '')
            "
            :prop="cln.value"
            :label="cln.label"
            :sortable="cln.sortable"
            :sort-method="cln.sortMethod"
            :type="cln.type"
            :width="cln.width"
            :align="cln.align || 'center'"
            :class-name="cln.className"
            :show-overflow-tooltip="tableNoWrap"
          >
            <template v-if="cln.header" #header="scope">
              <slot v-bind="scope" :name="cln.header" />
            </template>
            <template v-if="cln.slot" #default="scope">
              <slot v-bind="scope" :name="cln.slot" />
            </template>
            <template v-else-if="cln.slotRender" #default="scope">
              <com-functionRender
                :render="cln.slotRender"
                :data="{
                  row: scope.row,
                  column: cln,
                  index: scope.$index,
                }"
              />
            </template>
          </el-table-column>
        </template>
      </template>
    </el-table>
  </div>
</template>

<script>
import { treeToArray } from '@utils'
const PARENT_POSSIBLE_VALUE = [0, '0', ''] // 一级父节点可能值
export default {
  name: "TreeTabel",
  props: {
    tableNoWrap: {
      type: Boolean,
      default: false
    },
    tableData: {
      type: Array,
      default: () => []
    },
    tableColumn: {
      type: Array,
      default: () => []
    },
    parentName: {
      type: String,
      default: 'parentId'
    },
    idName: {
      type: String,
      default: 'id'
    },
    initSelect: {
      type: Array,
      default: () => []
    }, // eslint-disable-next-line vue/require-default-prop
    pid: {
      // eslint-disable-next-line vue/require-prop-type-constructor
      type: String | Number
    }
  },
  data() {
    return {
      initSelectId: []
    }
  },
  computed: {

  },
  watch: {
    initSelect: {
      handler(val) {
        if (!val.length) return
        this.initSelectId = val.map(item => item[this.idName])
      },
      immediate: true
    }
  },
  mounted() {
    if (this.pid) { PARENT_POSSIBLE_VALUE.push(this.pid) }
    this.initData(this.tableData)
    this.checkParentIsSelect(this.tableData)
  },
  methods: {
    /* 表格数据添加是否选中的标志 */
    initData(data) {
      data.forEach((item) => {
        item.isSelect = this.initSelectId.includes(item[this.idName])
        if (item.isSelect) {
          this.$refs.treeTabel.toggleRowSelection(item, true)
        }
        if (item.children && item.children.length) {
          this.initData(item.children)
        }
      })
    },
    /* 检测父节点是否勾选 */
    checkParentIsSelect(data) {
      data.forEach((item, index) => {
        if (item.children && item.children.length) {
          const isAllSelect = item.children.filter(iten => iten.isSelect)
          const itemLen = item.children.length
          const isSelectLen = isAllSelect.length
          if (isSelectLen === itemLen) {
            this.$refs.treeTabel.toggleRowSelection(item, true)
          }
          if (isSelectLen && isSelectLen !== itemLen) {
            item.isSelect = ''
          }
          this.checkParentIsSelect(item.children)
        }
      })
    },
    /* 复选框点击事件 */
    setRowIsSelect(selection, row) {
      // 当点击父级点复选框时，当前的状态可能为未知状态，所以当前行状态设为false并选中，即可实现子级点全选效果
      if (row.isSelect === "") {
        row.isSelect = false
        this.$refs.treeTabel.toggleRowSelection(row, true)
      }
      row.isSelect = !row.isSelect
      const that = this

      function selectAllChildrens(data) {
        data.forEach((item) => {
          item.isSelect = row.isSelect
          that.$refs.treeTabel.toggleRowSelection(item, row.isSelect)
          if (item.children && item.children.length) {
            selectAllChildrens(item.children)
          }
        })
      }
      function getSelectStatus(selectStatuaArr, data) {
        data.forEach((childrenItem) => {
          selectStatuaArr.push(childrenItem.isSelect)
          if (childrenItem.children && childrenItem.children.length) {
            getSelectStatus(selectStatuaArr, childrenItem.children)
          }
        })
        return selectStatuaArr
      }
      function getLevelStatus(row) {
        // 如果当前节点的parantId =0 并且有子节点，则为1
        // 如果当前节点的parantId !=0 并且子节点没有子节点 则为3

        if (!row[that.parentName] || PARENT_POSSIBLE_VALUE.includes(row[that.parentName])) {
          if (row.children && row.children.length) {
            return 1
          } else {
            return 4
          }
        } else {
          if (!row.children || !row.children.length) {
            return 3
          } else {
            return 2
          }
        }
      }
      let result = {}
      // 获取明确的节点
      function getExplicitNode(data, parentId) {
        data.forEach((item) => {
          if (item[that.idName] === parentId) {
            result = item
          }
          if (item.children && item.children.length) {
            getExplicitNode(item.children, parentId)
          }
        })
        return result
      }
      function operateLastLeve(row) {
        // 操作的是子节点  1、获取父节点  2、判断子节点选中个数，如果全部选中则父节点设为选中状态，如果都不选中，则为不选中状态，如果部分选择，则设为不明确状态
        let selectStatuaArr = []
        const item = getExplicitNode(that.tableData, row[that.parentName])
        selectStatuaArr = getSelectStatus(selectStatuaArr, item.children)
        if (
          selectStatuaArr.every((selectItem) => {
            return selectItem === true
          })
        ) {
          item.isSelect = true
          that.$refs.treeTabel.toggleRowSelection(item, true)
        } else if (
          selectStatuaArr.every((selectItem) => {
            return selectItem === false
          })
        ) {
          item.isSelect = false
          that.$refs.treeTabel.toggleRowSelection(item, false)
        } else {
          item.isSelect = ""
        }
        // 则还有父级
        if (item[that.parentName] && !PARENT_POSSIBLE_VALUE.includes(row[that.parentName])) {
          operateLastLeve(item)
        }
      }
      // 判断操作的是子级点复选框还是父级点复选框，如果是父级点，则控制子级点的全选和不全选

      // 1、只是父级 2、既是子集，又是父级 3、只是子级
      const levelSataus = getLevelStatus(row)
      if (levelSataus === 1) {
        selectAllChildrens(row.children)
      } else if (levelSataus === 2) {
        selectAllChildrens(row.children)
        operateLastLeve(row)
      } else if (levelSataus === 3) {
        operateLastLeve(row)
      }
    },
    /* 检测表格数据是否全选 */
    checkIsAllSelect() {
      this.onetreeTabelIsSelect = []
      this.tableData.forEach((item) => {
        this.onetreeTabelIsSelect.push(item.isSelect)
      })
      // 判断一级是否是全选.如果一级全为true，则设置为取消全选，否则全选
      const isAllSelect = this.onetreeTabelIsSelect.every((selectStatusItem) => {
        return selectStatusItem === true
      })
      return isAllSelect
    },
    /* 表格全选事件 */
    selectAllFun(selection) {
      const isAllSelect = this.checkIsAllSelect()
      this.tableData.forEach((item) => {
        item.isSelect = isAllSelect
        this.$refs.treeTabel.toggleRowSelection(item, !isAllSelect)
        this.setRowIsSelect(selection, item)
      })
    },
    /* 表格行样式 当当前行的状态为不明确状态时，添加样式，使其复选框为不明确状态样式 */
    rowClassNameFun({ row }) {
      if (row.isSelect === "") {
        return "is-indeterminate"
      }
    },
    /* 表格标题样式 当一级目录有为不明确状态时，添加样式，使其全选复选框为不明确状态样式 */
    headerRowClassName({ row }) {
      const onetreeTabelIsSelect = []
      this.tableData.forEach((item) => {
        onetreeTabelIsSelect.push(item.isSelect)
      })
      if (onetreeTabelIsSelect.includes("")) {
        return "is-indeterminate"
      }
      return ""
    },
    /* 获取选中的数据 */
    getSelcetionData() {
      return treeToArray(this.tableData).filter(item => {
        return item.isSelect
      })
    }

  }
}
</script>
<style lang="scss" scoped>
.treeTabel-wrap {
	&::v-deep {
		.el-table .cell{
				word-break: keep-all;
				white-space: nowrap;
		}
		.el-table th>.cell {
				width: auto;
		}
		.is-indeterminate .el-checkbox__input .el-checkbox__inner {
			background-color: #307ff5 !important;
			border-color: #307ff5 !important;
			color: #fff !important;
		}
		.is-indeterminate .el-checkbox__input.is-checked .el-checkbox__inner::after {
			transform: scale(0.45);
		}
		.is-indeterminate .el-checkbox__input .el-checkbox__inner {
			background-color: #f2f6fc;
			border-color: #dcdfe6;
		}
		.is-indeterminate .el-checkbox__input .el-checkbox__inner::after {
			border-color: #c0c4cc !important;
			background-color: #c0c4cc;
		}
		// th .el-checkbox__inner {
		// 	display: none !important;
		// }
		.is-indeterminate .el-checkbox__input .el-checkbox__inner::after {
			content: "";
			position: absolute;
			display: block;
			background-color: #fff;
			height: 2px;
			transform: scale(0.5);
			left: 0;
			right: 0;
			top: 5px;
			width: auto !important;
		}
		.el-checkbox__inner {
			display: block !important;
		}
		.el-checkbox {
			display: block !important;
		}
	}

}

</style>
